home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / chat / reflect.000 / reflect / 3.0b3 / distribute.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  18.0 KB  |  671 lines

  1. /*
  2.  
  3. Copyright 1993, 1994, Cornell University
  4.  
  5. Cornell hereby grants permission to use, copy, modify, and distribute this program for any purpose 
  6. and without fee, provided that these copyright and permission notices appear on all copies and 
  7. supporting documentation, the name of Cornell not be used in advertising or publicity pertaining 
  8. to distribution of the program without specific prior permission, notice be given in supporting 
  9. documentation that copying and distribution is by permission of Cornell.  CORNELL MAKES NO 
  10. REPRESENTATIONS OR WARRANTEES, EXPRESS OR IMPLIED.  By way of example, but not limitation, 
  11. CORNELL MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR 
  12. PURPOSE OR THAT THE USE OF THIS SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, 
  13. TRADEMARKS, OR OTHER RIGHTS.  Cornell shall not be held liable for any liability with respect to 
  14. any claim by the user or any other party arising from use of the program.
  15.  
  16. This material is partially based on work sponsored by the National Science Foundation under Cooperative 
  17. Agreement No. NCR-9318337.  The government has certain rights in this material.
  18.  
  19. */
  20.  
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <varargs.h>
  25. #include <signal.h>
  26. #include <errno.h>
  27. #include <malloc.h>
  28. #include <sys/types.h>
  29. #include <sys/param.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/socket.h>
  32. #include <sys/time.h>
  33.  
  34. #ifndef LINUX
  35. #include <sys/socketvar.h>
  36. #include <net/route.h>
  37. #endif
  38.  
  39. #include <net/if.h>
  40. #include <netinet/in.h>
  41.  
  42. #include "reflect.h"
  43. #include "refmon.h"
  44. #include "rtp.h"
  45. #include "globals.h"
  46.  
  47. void write_cmsg(msg,cltptr)
  48.     short       msg;
  49.     client      *cltptr;
  50.  
  51. {
  52.     VideoPacketHeader pkt;
  53.  
  54.     pkt.routing.src.family = htons(kReflector);
  55.     bcopy(&myaddr.sin_addr.s_addr,&pkt.routing.src.addr,4);
  56.     pkt.routing.src.addr = 0;
  57.     pkt.routing.src.port = htons(VID_PORT);
  58.  
  59.     pkt.routing.dest.family = htons(kClient);
  60.     bcopy(&cltptr->clnt_addr.addr,&pkt.routing.dest.addr,4);
  61.     pkt.routing.dest.port = htons(VID_PORT);
  62.  
  63.     pkt.seqNum = 0;
  64.     pkt.dataType = htons(kControlType);
  65.     pkt.len = htons(sizeof(VideoPacketHeader));
  66.     pkt.message = htons(msg);
  67.  
  68.     write_pkt(&pkt,cltptr);
  69. }
  70.  
  71. void write_close(cltptr,clientIP)
  72.     client      *cltptr;
  73.     unsigned long clientIP;
  74.  
  75. {
  76.     VideoPacketHeader pkt;
  77.     struct in_addr in;
  78.  
  79.     in.s_addr = clientIP;
  80.     dolog("sending a close to client %s on behalf of %s\n",cltptr->clnt_config.name,inet_ntoa(in));
  81.  
  82.     pkt.routing.src.family = htons(kReflector);
  83.     bcopy(&clientIP,&pkt.routing.src.addr,4);
  84.     pkt.routing.src.port = htons(VID_PORT);
  85.  
  86.     pkt.routing.dest.family = htons(kClient);
  87.     bcopy(&cltptr->clnt_addr.addr,&pkt.routing.dest.addr,4);
  88.     pkt.routing.dest.port = htons(VID_PORT);
  89.  
  90.     pkt.seqNum = 0xffffffff;
  91.     pkt.dataType = htons(kConfigVideoType);
  92.     pkt.len = htons(sizeof(VideoPacketHeader));
  93.     pkt.message = htons(kCloseConnection);
  94.  
  95.     write_pkt(&pkt,cltptr);
  96. }
  97.  
  98.  
  99.  
  100. void write_pkt(vidptr,cltptr)
  101.     VideoPacketHeader        *vidptr;
  102.     client                   *cltptr;
  103. {
  104.     struct in_addr in;
  105.  
  106.     if (cltptr->clnt_flags & REF3_ORIGIN)
  107.        cltptr = cltptr->clnt_pptr;
  108.  
  109.     if (cltptr->clnt_flags & HOLD_DOWN)
  110.        return;
  111.  
  112. #ifdef DEBUG
  113.     if (debug)
  114.     {
  115.        in.s_addr = cltptr->clnt_addr.addr;
  116.        printf("sending to %s\n",inet_ntoa(in));
  117.     }
  118. #endif
  119.  
  120.     cltptr->clnt_stimer = 0;
  121.  
  122.     pkts_out++;
  123.     bytes_out += ntohs(vidptr->len);
  124.  
  125.     if (sendto(vid_sock,vidptr,ntohs(vidptr->len),0,&cltptr->clnt_addr,sizeof(struct sockaddr_in)) != ntohs(vidptr->len))
  126.        dolog("sendto error %d client %s\n",errno,cltptr->clnt_config.name);
  127. }
  128.  
  129.  
  130. write_msg(clnt_addr,type,cptr)
  131.     struct sockaddr_in  *clnt_addr;
  132.     short               type;
  133.     char                *cptr;
  134. {
  135.     static char         buf[MAXMSG];
  136.     VideoPacketHeader   *pkt=(VideoPacketHeader *)buf;
  137.     char                *tmp,clen;
  138.     short               mlen,nlen,cnt;
  139.     int                 len;
  140.  
  141.     pkt->routing.src.family = htons(kReflector);
  142.     bcopy(&myaddr.sin_addr.s_addr,&pkt->routing.src.addr,4);
  143.     pkt->routing.src.port = htons(VID_PORT);
  144.  
  145.     pkt->routing.dest.family = htons(kClient);
  146.     bcopy(&clnt_addr->sin_addr,&pkt->routing.dest.addr,4);
  147.     pkt->routing.dest.port = htons(VID_PORT);
  148.  
  149.     pkt->seqNum = 0;
  150.     pkt->dataType = htons(type);
  151.     pkt->message = 0;
  152.  
  153.     mlen = strlen(cptr);
  154.  
  155.     for (cnt = 0; cnt < mlen; cnt++)
  156.     {
  157.  
  158.        if (*(cptr+cnt) == '\n')
  159.           *(cptr+cnt) = '\r';
  160.     }
  161.  
  162.     len = sizeof(VideoPacketHeader) + mlen + 2;
  163.  
  164.     pkt->len = htons(len);
  165.  
  166.     tmp = (char *) (pkt+1);
  167.  
  168.     if (type == kMessageType1)
  169.     {
  170.        len--;
  171.        pkt->len = htons(len);
  172.        clen = mlen;
  173.        *tmp = clen;
  174.        bcopy(cptr,(char *)(tmp+1),mlen);
  175.     }
  176.     else
  177.     {
  178.        nlen = htons(mlen);
  179.        bcopy(&nlen,tmp,2);
  180.        bcopy(cptr,(char *)(tmp+2),mlen);
  181.     }
  182.  
  183. #ifdef DEBUG
  184.     if (debug)
  185.        printf("sending reflector message %s to client at %s\n",cptr,inet_ntoa(clnt_addr->sin_addr));
  186. #endif
  187.  
  188.     pkts_out++;
  189.     bytes_out += len;
  190.  
  191.     if (sendto(vid_sock,buf,len,0,clnt_addr,sizeof(struct sockaddr_in)) != len)
  192.     {
  193.        dolog("sendto error on old video socket");
  194.     }
  195. }
  196.  
  197. void distribute(vidptr,cltptr,all)
  198.    VideoPacketHeader *vidptr;
  199.    client *cltptr;
  200.    char   all;
  201. {
  202.     client         *ctmp;
  203.     slist          *sptr;
  204.     struct in_addr in;
  205.     int            len,cnt;
  206.     short          ref_ucast_sent[MAXSRCREF];    
  207.     short          mcast_sent = FALSE;
  208.  
  209.     cltptr->clnt_hdloop = 0;
  210.     cltptr->clnt_flags &= ~HOLD_DOWN;
  211.  
  212.     if (all == FALSE)
  213.     {
  214.        for (cnt=0; cnt < MAXSRCREF; cnt++)
  215.           ref_ucast_sent[cnt] = 0;
  216.  
  217.        sptr = cltptr->clnt_vlist;
  218.        while (sptr)
  219.        {
  220.           if (sptr->snd_client->clnt_flags & REF3_ORIGIN)
  221.           {
  222.              if ((ctmp = sptr->snd_client->clnt_pptr) == NULL)
  223.              {
  224.                 dolog("REF3_ORIGIN client without a parent in distribute\n");
  225.                 delete_client(cltptr);
  226.                 return;
  227.              }
  228.  
  229.              if ((ctmp->clnt_flags & REF3_SERVER) == 0)
  230.              {
  231.                 dolog("REF3_ORIGIN client's parent is not a REF3_SERVER\n");
  232.                 delete_client(cltptr);
  233.                 return;
  234.              }
  235.  
  236.              if ((ref_ucast_sent[ctmp->clnt_id] == 0) && (cltptr->clnt_flags & REF3_ORIGIN) == 0)
  237.              {
  238.                 ref_ucast_sent[ctmp->clnt_id] = 1;
  239.                 write_pkt(vidptr,ctmp);
  240.              }
  241.  
  242.              sptr = sptr->snd_nptr;
  243.              continue;
  244.           }
  245.  
  246.           if (sptr->snd_client->clnt_flags & CLIENT)
  247.              write_pkt(vidptr,sptr->snd_client);
  248.  
  249.           sptr = sptr->snd_nptr;
  250.        }
  251.  
  252.        ctmp = chead;
  253.        while (ctmp != NULL)
  254.        {
  255.           if (ctmp->clnt_flags & (BCC_CLIENT | BCC_GCLIENT))
  256.              write_pkt(vidptr,ctmp);
  257.           ctmp = ctmp->clnt_nptr;
  258.        }
  259.  
  260.        /* if necessary, distribute this cu-seeme video packet to all the NV clients */
  261.        if ((cltptr->clnt_flags & (NV_UCLIENT | NV_MCLIENT)) == 0)
  262.        {
  263.           if (nv_out_mcast_sock || nv_inout_mcast_sock || send_to_nv(cltptr)) 
  264.              nv_wrt(cltptr,vidptr);
  265.        }
  266.     }
  267.     else
  268.     {
  269.        ctmp = chead;
  270.        while (ctmp != NULL)
  271.        {
  272.           if ((ctmp->clnt_flags & CLIENT) && ((self_reflect == 1) || (cltptr != ctmp)))
  273.              write_pkt(vidptr,ctmp);
  274.           else
  275.              if ((ctmp->clnt_flags & REF3_SERVER) && ((cltptr->clnt_flags & (REF3_SERVER | REF3_ORIGIN)) == 0))
  276.                 write_pkt(vidptr,ctmp);
  277.              else
  278.                 if ((ctmp->clnt_flags & (BCC_CLIENT | BCC_GCLIENT)) && (cltptr != ctmp))
  279.                    write_pkt(vidptr,ctmp);
  280.           ctmp = ctmp->clnt_nptr;
  281.        }
  282.     }
  283.  
  284. #ifdef MULTI
  285.     if (rfout_mcast.sin_addr.s_addr)
  286.        rf_mcast_wrt(vidptr);
  287.  
  288.     if ((cltptr->clnt_flags & (REF2_SERVER | REF2_ORIGIN)) == 0)
  289.        if (inout_mcast.sin_addr.s_addr)
  290.           inout_mcast_wrt(vidptr);
  291. #endif
  292. }
  293.  
  294.  
  295. void distribute_audio(vidptr,cltptr)
  296.    VideoPacketHeader *vidptr;
  297.    client *cltptr;
  298. {
  299.     client         *ctmp;
  300.     unsigned char  *cptr,*cptr1;
  301.     vat_client     *mtmp;
  302.     slist          *sptr;
  303.     struct in_addr in;
  304.     int            len,cnt;
  305.     short          ref_ucast_sent[MAXSRCREF];    
  306.     struct sockaddr_in tmp1;
  307.     vat_hdr_t      *vat_hdr;
  308.     unsigned long  ul;
  309.     char          *tmp;
  310.  
  311.  
  312.     cltptr->clnt_hdloop = 0;
  313.     cltptr->clnt_flags &= ~HOLD_DOWN;
  314.  
  315.     if (cltptr->clnt_talker == 0)
  316.        dolog("%s is speaking\n",cltptr->clnt_config.name);
  317.  
  318.     if (cltptr->clnt_talker++ > 50)
  319.        cltptr->clnt_talker = 0;
  320.  
  321.     if (cltptr->clnt_config.sendMode == 0)
  322.     {
  323.        ctmp = chead;
  324.        while (ctmp != NULL)
  325.        {
  326.           if (ctmp->clnt_flags & CLIENT)
  327.              if ((ctmp->clnt_config.flags & REC_AUDIO) && (ctmp->clnt_config.flags & WANT_LURCKERS))
  328.                 write_pkt(vidptr,ctmp);
  329.          ctmp = ctmp->clnt_nptr;
  330.        }
  331.     }
  332.     else
  333.     {
  334.        for (cnt=0; cnt < MAXSRCREF; cnt++)
  335.           ref_ucast_sent[cnt] = 0;
  336.  
  337.        sptr = cltptr->clnt_alist;
  338.        while (sptr)
  339.        {
  340.           if (sptr->snd_client->clnt_flags & REF3_ORIGIN)
  341.           {
  342.              if ((ctmp = sptr->snd_client->clnt_pptr) == NULL)
  343.              {
  344.                 dolog("REF3_ORIGIN client without a parent in distribute_audio\n");
  345.                 delete_client(cltptr);
  346.                 return;
  347.              }
  348.  
  349.              if ((ctmp->clnt_flags & REF3_SERVER) == 0)
  350.              {
  351.                 dolog("REF3_ORIGIN client's parent is not a REF3_SERVER\n");
  352.                 delete_client(cltptr);
  353.                 return;
  354.              }
  355.  
  356.              if ((ref_ucast_sent[ctmp->clnt_id] == 0) && (cltptr->clnt_flags & REF3_ORIGIN) == 0)
  357.              {
  358.                 ref_ucast_sent[ctmp->clnt_id] = 1;
  359.                 write_pkt(vidptr,ctmp);
  360.              }
  361.  
  362.              sptr = sptr->snd_nptr;
  363.              continue;
  364.           }
  365.  
  366.           if (sptr->snd_client->clnt_flags & CLIENT)
  367.              write_pkt(vidptr,sptr->snd_client);
  368.           sptr = sptr->snd_nptr;
  369.        }
  370.     }
  371.  
  372.     ctmp = chead;
  373.     while (ctmp != NULL)
  374.     {
  375.        if (ctmp->clnt_flags & (BCC_CLIENT | BCC_GCLIENT))
  376.           write_pkt(vidptr,ctmp);
  377.        ctmp = ctmp->clnt_nptr;
  378.     }
  379.  
  380. #ifdef MULTI
  381.     if (rfout_mcast.sin_addr.s_addr)
  382.        rf_mcast_wrt(vidptr);
  383.  
  384.     if ((cltptr->clnt_flags & (REF2_SERVER | REF2_ORIGIN)) == 0)
  385.        if (inout_mcast.sin_addr.s_addr)
  386.           inout_mcast_wrt(vidptr);
  387. #endif
  388.  
  389.  
  390.     cptr = ((unsigned char *) vidptr) + HEADERLEN;
  391.     len = vidptr->len - HEADERLEN;
  392.     mtmp = mhead;
  393.    
  394.     if ((mtmp != NULL) || (vat_out_mcast_sock)) 
  395.     {
  396.        /* 
  397.           the following code adds a speaker id to the maven/vat audio
  398.           packet being sent.  See vat_hdr_t.   
  399.        */
  400.  
  401.        tmp = (char *) cptr;
  402.        tmp -= 4;
  403.  
  404.        bcopy((char *)cptr, tmp, sizeof(vat_hdr_t));
  405.  
  406.        cptr += (sizeof(vat_hdr_t) - 4);
  407.  
  408.        ul = cltptr->clnt_addr.addr;
  409.        cptr1 = (unsigned char *) &ul;
  410.  
  411.        *cptr++ = *cptr1++;
  412.        *cptr++ = *cptr1++;
  413.        *cptr++ = *cptr1++;
  414.        *cptr++ = *cptr1++;
  415.  
  416.        cptr = (unsigned char *) tmp;
  417.  
  418.        vat_hdr = (vat_hdr_t *) cptr;
  419.  
  420.        /* set the number of speaker id's to 1 */
  421.        vat_hdr->nsid = (vat_hdr->nsid & ~NSID_MASK) | 1;
  422.  
  423.        /* set the conference id in this vat audio packet to the vat_confid */
  424.  
  425.       vat_hdr->confid = htons(vat_confid);
  426.  
  427.       len += 4;
  428.  
  429.       while (mtmp != NULL) 
  430.       {
  431.          if ((mtmp->mvn_recv_type == UCAST) && ((mtmp->mvn_flags & VAT_MIXER_CLIENT) == 0))
  432. #ifdef DEBUG
  433.            if (debug)
  434.        {
  435.           in.s_addr = mtmp->mvn_addr.addr; 
  436.           printf("reflecting CUSEEME audio to ucast maven %s \n", inet_ntoa(in));
  437.            }
  438. #endif
  439.            if (sendto(maven_sock,cptr,len,0,&mtmp->mvn_addr,sizeof(struct sockaddr_in)) != len)
  440.               dolog("maven sendto error in distribute\n");
  441.  
  442.          mtmp = mtmp->mvn_nptr;
  443.       }
  444.  
  445.       tmp1.sin_family = AF_INET;
  446.       tmp1.sin_addr.s_addr = htonl(vat_out_mcast.sin_addr.s_addr);
  447.       tmp1.sin_port = htons(vat_port);
  448.  
  449.       /* 
  450.          if there are any mcast clients then we want to distribute this audio
  451.          to them if vat_inout_mcast_sock has been bound...
  452.       */
  453.  
  454.       if (num_vat_clients(MCAST)) 
  455.       {
  456.          if (vat_inout_mcast_sock) 
  457.          {
  458.             if (sendto(vat_inout_mcast_sock,cptr,len,0,&tmp1,sizeof(struct sockaddr_in)) != len)
  459.                dolog("mcast sendto error");
  460.          }
  461.       }
  462.       else 
  463.          if (vat_out_mcast_sock) 
  464.          {
  465.             /* 
  466.                else, (ie if there are no mcast vat/maven clients) if vat_out_mcast_sock
  467.                has been bound, blindly send this vat stream onto the mcast address 
  468.             */
  469.  
  470.             if (sendto(vat_out_mcast_sock,cptr,len,0,&tmp1,sizeof(struct sockaddr_in)) != len)
  471.                dolog("mcast sendto error");
  472.          }
  473.     }
  474. }
  475.  
  476.  
  477. void distribute_aux(vidptr,cltptr)
  478.    VideoPacketHeader *vidptr;
  479.    client *cltptr;
  480. {
  481.     client         *ctmp;
  482.     slist          *sptr;
  483.     unsigned char  *aux;
  484.     struct in_addr in;
  485.     int            len,cnt;
  486.     unsigned long  aux_mask;
  487.     short          ref_ucast_sent[MAXSRCREF];    
  488.     char           tmp[100];
  489.  
  490.     aux = (unsigned char *) ((char *)vidptr+HEADERLEN+4);
  491.     bcopy(aux,&aux_mask,4);
  492.     aux_mask = ntohl(aux_mask); 
  493.     dolog("AUX data packet mask is %ld\n",aux_mask);
  494.     cltptr->clnt_hdloop = 0;
  495.     cltptr->clnt_flags &= ~HOLD_DOWN;
  496.  
  497.     for (cnt=0; cnt < MAXSRCREF; cnt++)
  498.        ref_ucast_sent[cnt] = 0;
  499.  
  500.     sptr = cltptr->clnt_xlist;
  501.     while (sptr)
  502.     {
  503.        if ((sptr->snd_auxmask & aux_mask) != 0)
  504.        {
  505.           if (sptr->snd_client->clnt_flags & REF3_ORIGIN)
  506.           {
  507.              if ((ctmp = sptr->snd_client->clnt_pptr) == NULL)
  508.              {
  509.                 dolog("REF3_ORIGIN client without a parent in distribute\n");
  510.                 delete_client(cltptr);
  511.                 return;
  512.              }
  513.  
  514.              if ((ctmp->clnt_flags & REF3_SERVER) == 0)
  515.              {
  516.                 dolog("REF3_ORIGIN client's parent is not a REF3_SERVER\n");
  517.                 delete_client(cltptr);
  518.                 return;
  519.              }
  520.  
  521.              if ((ref_ucast_sent[ctmp->clnt_id] == 0) && (cltptr->clnt_flags & REF3_ORIGIN) == 0)
  522.              {
  523.                 ref_ucast_sent[ctmp->clnt_id] = 1;
  524.                 write_pkt(vidptr,ctmp);
  525.              }
  526.  
  527.              sptr = sptr->snd_nptr;
  528.              continue;
  529.           }
  530.  
  531.           if (sptr->snd_client->clnt_flags & CLIENT)
  532.           {
  533.              in.s_addr = vidptr->routing.src.addr;
  534.              sprintf(tmp,"sending AUX data from %s ",inet_ntoa(in));
  535.              in.s_addr = sptr->snd_client->clnt_addr.addr;
  536.              dolog("%s to %s\n",tmp,inet_ntoa(in));
  537.              write_pkt(vidptr,sptr->snd_client);
  538.           }
  539.        }
  540.        sptr = sptr->snd_nptr;
  541.     }
  542.  
  543.     ctmp = chead;
  544.     while (ctmp != NULL)
  545.     {
  546.        if (ctmp->clnt_flags & (BCC_CLIENT | BCC_GCLIENT))
  547.           write_pkt(vidptr,ctmp);
  548.        ctmp = ctmp->clnt_nptr;
  549.     }
  550.  
  551. #ifdef MULTI
  552.     if (rfout_mcast.sin_addr.s_addr)
  553.        rf_mcast_wrt(vidptr);
  554.  
  555.     if ((cltptr->clnt_flags & (REF2_SERVER | REF2_ORIGIN)) == 0)
  556.        if (inout_mcast.sin_addr.s_addr)
  557.           inout_mcast_wrt(vidptr);
  558. #endif
  559. }
  560.  
  561.  
  562. /* distribute nv video to other nv's */
  563.  
  564. void distribute_nv(rtp_hdr_ptr,msglen,nvcptr)
  565.    struct rtphdr **rtp_hdr_ptr;
  566.    int           *msglen;
  567.    client        *nvcptr;
  568.  
  569. {
  570.     struct rtpopthdr    *optr;
  571.     struct rtpssrchdr   *sptr;
  572.     client              *ctmp;
  573.     short               err,len;
  574.     char                *cptr;
  575.  
  576.     cptr = (char *) (*rtp_hdr_ptr + 1);
  577.  
  578.     if ((*rtp_hdr_ptr)->rh_opts)
  579.     {
  580.        optr = (struct rtpopthdr *) cptr;
  581.  
  582.        if (!optr->roh_fin)
  583.        {
  584.       dolog("In distribute_nv, received rtp packet with more then one option\n");
  585.       return;
  586.        }
  587.        optr->roh_fin = 0;
  588.        cptr += 4*(optr->roh_optlen);
  589.     }
  590.  
  591.     (*rtp_hdr_ptr)->rh_opts = 1;
  592.  
  593.     len = cptr - (char *) *rtp_hdr_ptr;
  594.     bcopy((char *)*rtp_hdr_ptr,(char *)*rtp_hdr_ptr - sizeof(struct rtpssrchdr),len);
  595.  
  596.     *rtp_hdr_ptr = (struct rtphdr *) ((char *) *rtp_hdr_ptr - sizeof(struct rtpssrchdr));
  597.  
  598.     sptr = (struct rtpssrchdr *) ((char *) *rtp_hdr_ptr + len);
  599.  
  600.     sptr->rsh_fin = 1;
  601.     sptr->rsh_type = RTPOPT_SSRC;
  602.     sptr->rsh_optlen = 2;
  603.     sptr->rsh_id = htons(nvcptr->clnt_id);
  604.     sptr->rsh_addr = htonl(nvcptr->clnt_addr.addr);
  605.  
  606.     *msglen += sizeof(struct rtpssrchdr);
  607.  
  608.     ctmp = chead;
  609.     while (ctmp != NULL)
  610.     {
  611.        if ((ctmp->clnt_flags & NV_UCLIENT) && (ctmp != nvcptr))
  612.       if (err = (sendto(nv_ucast_sock,*rtp_hdr_ptr,*msglen,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in))) != *msglen)
  613.              dolog("ucast nv->nv sendto error %d\n",err);
  614.  
  615.        ctmp = ctmp->clnt_nptr;
  616.     }
  617.  
  618.     if ((nvcptr->clnt_flags & NV_MCLIENT) == 0)
  619.     {
  620.        if (nv_out_mcast_sock)
  621.        {
  622.           if (err = (sendto(nv_out_mcast_sock,*rtp_hdr_ptr,*msglen,0,&nv_out_mcast,sizeof(struct sockaddr_in))) != *msglen)
  623.              dolog("mcast nv->nv sendto error %d\n",err);
  624.        }
  625.  
  626.        if (nv_inout_mcast_sock)
  627.        {
  628.           if (err = (sendto(nv_inout_mcast_sock,*rtp_hdr_ptr,*msglen,0,&nv_inout_mcast,sizeof(struct sockaddr_in))) != *msglen)
  629.              dolog("mcast nv->nv sendto error %d\n",err);
  630.        }
  631.     }
  632. }
  633.  
  634.  
  635. /*
  636. void distribute_nv(msg,msglen,nvcptr)
  637.    unsigned char *msg;
  638.    int           msglen;
  639.    client        *nvcptr;
  640.  
  641. {
  642.     client         *ctmp;
  643.     short          err;
  644.  
  645.     ctmp = chead;
  646.     while (ctmp != NULL)
  647.     {
  648.        if ((ctmp->clnt_flags & NV_UCLIENT) && (ctmp != nvcptr))
  649.           if (err = (sendto(nv_ucast_sock,msg,msglen,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in))) != msglen)
  650.              dolog("ucast nv->nv sendto error %d\n",err);
  651.  
  652.        ctmp = ctmp->clnt_nptr;
  653.     }
  654.  
  655.     if ((nvcptr->clnt_flags & NV_MCLIENT) == 0)
  656.     {
  657.        if (nv_out_mcast_sock)
  658.        {
  659.           if (err = (sendto(nv_out_mcast_sock,msg,msglen,0,&nv_out_mcast,sizeof(struct sockaddr_in))) != msglen)
  660.              dolog("mcast nv->nv sendto error %d\n",err);
  661.        }
  662.  
  663.        if (nv_inout_mcast_sock)
  664.        {
  665.           if (err = (sendto(nv_inout_mcast_sock,msg,msglen,0,&nv_inout_mcast,sizeof(struct sockaddr_in))) != msglen)
  666.              dolog("mcast nv->nv sendto error %d\n",err);
  667.        }
  668.     }
  669. }
  670. */
  671.